Skip to content

byoc: support offchain mode without an Eth keystore#3906

Open
rickstaa wants to merge 1 commit into
masterfrom
byoc-offchain-no-eth
Open

byoc: support offchain mode without an Eth keystore#3906
rickstaa wants to merge 1 commit into
masterfrom
byoc-offchain-no-eth

Conversation

@rickstaa

Copy link
Copy Markdown
Member

Summary

Fixes #3905. BYOC currently requires -ethPassword=... on both gateway and orchestrator even in -network offchain mode — a throwaway keystore exists only to satisfy a vestigial signing requirement. After this PR, BYOC inherits transcoding's existing offchain story: no keystore, no -ethUrl, just -network offchain.

Root cause (recap from #3905)

Both halves of the signing flow are already offchain-aware:

BYOC's wrapper code prevented that bypass from being reached:

  1. byoc/job_gateway.gogetJobSender always prefixed "0x", producing the literal string "0x" for empty sigs.
  2. byoc/job_orchestrator.goverifyTokenCreds only stripped "0x" when len(Sig) > 130, so the literal "0x" passed through to hex.DecodeString and failed.

Changes

  • byoc/job_gateway.go — extracted encodeJobSig() that returns "" for empty sigs and "0x" + hex otherwise.
  • byoc/job_orchestrator.goverifyTokenCreds unconditionally trims a "0x" prefix via strings.TrimPrefix. Empty sig now decodes to empty bytes, VerifySig short-circuits to true offchain. Also fixed a missing format verb in the existing Unable to hex-decode signature log line.
  • TestsTestEncodeJobSig (helper), TestVerifyTokenCreds_OffchainEmptySig (round-trip), TestVerifyTokenCreds_StripsHexPrefix (regression for short prefixed sigs).

Test plan

  • go test ./byoc/... passes (existing + new tests)
  • go build ./byoc/... clean
  • Manual E2E: BYOC docker-compose with -network offchain on both nodes, no -ethPassword, no -ethUrl. Capability registers, /process/request/<suffix> round-trips through gateway → orchestrator → worker container. (Will validate in livepeer-python-gateway hello-world example once this lands.)

Context

Surfaced while building a Pipeline SDK hello-world test against unmodified go-livepeer. The example currently uses -ethPassword=secret-password as a workaround — once this lands, the compose drops the keystore flag entirely.

🤖 Generated with Claude Code

In -network offchain mode the broadcaster's Sign() returns empty bytes
(core/broadcaster.go:14) and the orchestrator's VerifySig() short-circuits
to true (core/orchestrator.go:66) — both already offchain-aware. BYOC
should inherit that behaviour but didn't because:

- byoc/job_gateway.go's getJobSender always prefixed the encoded signature
  with "0x", producing the literal string "0x" for empty sigs.
- byoc/job_orchestrator.go's verifyTokenCreds only stripped the prefix when
  len > 130, so "0x" passed through to hex.DecodeString and failed with
  "invalid byte: U+0078 'x'", aborting before VerifySig's offchain bypass
  could run.

Fix:
- encodeJobSig() returns "" for empty sigs, "0x" + hex otherwise.
- verifyTokenCreds() unconditionally trims a "0x" prefix; an empty sig now
  decodes to empty bytes and VerifySig short-circuits to true offchain.

Also fixes a missing format verb in the existing "Unable to hex-decode
signature" log line.

Tests cover both helpers plus the verifyTokenCreds round-trip with empty
and "0x"-prefixed sigs.

After this change a BYOC stack can run with just -network offchain on both
gateway and orchestrator — no -ethPassword, no auto-generated keystore,
no -ethUrl.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Apr 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.71429% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 32.92286%. Comparing base (9e68815) to head (c8e674f).

Files with missing lines Patch % Lines
byoc/job_orchestrator.go 50.00000% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@                 Coverage Diff                 @@
##              master       #3906         +/-   ##
===================================================
+ Coverage   32.87450%   32.92286%   +0.04836%     
===================================================
  Files            171         171                 
  Lines          42063       42065          +2     
===================================================
+ Hits           13828       13849         +21     
+ Misses         27194       27173         -21     
- Partials        1041        1043          +2     
Files with missing lines Coverage Δ
byoc/job_gateway.go 44.08946% <100.00000%> (+0.72376%) ⬆️
byoc/job_orchestrator.go 49.45946% <50.00000%> (+0.80355%) ⬆️

... and 4 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9e68815...c8e674f. Read the comment docs.

Files with missing lines Coverage Δ
byoc/job_gateway.go 44.08946% <100.00000%> (+0.72376%) ⬆️
byoc/job_orchestrator.go 49.45946% <50.00000%> (+0.80355%) ⬆️

... and 4 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

rickstaa added a commit to livepeer/livepeer-python-gateway that referenced this pull request May 8, 2026
The TODO referenced switching examples to bare `-network offchain` once
livepeer/go-livepeer#3906 lands. Current setup (on-chain Arbitrum +
pricePerUnit 0) works correctly today; the only cost is some 429 noise
from the public Arbitrum RPC. Tracked in the SDK epic (#8); no need to
keep the comment in every compose.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

go Pull requests that update Go code

Projects

No open projects
Status: Triage

Development

Successfully merging this pull request may close these issues.

BYOC: requires Eth keystore in -network offchain mode

1 participant